package com.atxiaodei.nio.nioday01;

import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;

/**
 * @author wangmeng
 * @date 2020/9/13
 *
 * 在我们对数组或者集合类进行操作的时候，经常会遇到这样的需求，比如：
 *
 * 是否包含某一个“匹配规则”的元素
 * 是否所有的元素都符合某一个“匹配规则”
 * 是否所有元素都不符合某一个“匹配规则”
 * 查找第一个符合“匹配规则”的元素
 * 查找任意一个符合“匹配规则”的元素
 * 这些需求如果用for循环去写的话，还是比较麻烦的，需要使用到for循环和break！本节就介绍一个如何用Stream API来实现“查找与匹配”。
 *
 * 不多说，直接干
 **/
public class StreamApi9查找与匹配元素 {

    StreamTestVo e1 = new StreamTestVo(1,23,"M","Rick","Beethovan");
    StreamTestVo e2 = new StreamTestVo(2,13,"F","Martina","Hengis");
    StreamTestVo e3 = new StreamTestVo(3,43,"M","Ricky","Martin");
    StreamTestVo e4 = new StreamTestVo(4,26,"M","Jon","Lowman");
    StreamTestVo e5 = new StreamTestVo(5,19,"F","Cristine","Maria");
    StreamTestVo e6 = new StreamTestVo(6,15,"M","David","Feezor");
    StreamTestVo e7 = new StreamTestVo(7,68,"F","Melissa","Roy");
    StreamTestVo e8 = new StreamTestVo(8,79,"M","Alex","Gussin");
    StreamTestVo e9 = new StreamTestVo(9,15,"F","Neetu","Singh");
    StreamTestVo e10 = new StreamTestVo(10,45,"M","Naveen","Jain");


    List<StreamTestVo> list = Arrays.asList(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);

    /**
     * 查找员工列表中是否包含年龄大于70的员工
     */
    @Test
    public void test1(){
        // 之前的for循环就不实现了，现在主要就是学习jdk8特性
        // ① 先用匿名内部类实现
        boolean b = list.stream()
                .anyMatch(new Predicate<StreamTestVo>() {
                    @Override
                    public boolean test(StreamTestVo streamTestVo) {
                        return streamTestVo.getAge() > 70;
                    }
                });
        System.out.println(b);
        // ② 如果我们使用Stream API就是下面的一行代码，其中使用到了我们之前学过的"谓词逻辑"。
        boolean b1 = list.stream()
                .anyMatch(StreamTestVo.ageGreaterThan70);
        System.out.println(b);
        // 用lamdba表达式替换谓词逻辑
        boolean b2 = list.stream()
                .anyMatch(x -> x.getAge() > 70);
        System.out.println(b2);
        // 总结：所以，我们介绍了第一个匹配规则函数：anyMatch，判断Stream流中是否包含某一个“匹配规则”的元素。这个匹配规则可以是lambda表达式或者谓词。
    }

    @Test
    public void test2(){
        // 是否所有员工的年龄都大于70岁？allMatch匹配规则函数：判断是够Stream流中的所有元素都符合某一个"匹配规则"。
        boolean b = list.stream()
                .allMatch(x -> x.getAge() > 70);
        System.out.println(b);

//        是否不存在小于70岁的员工？noneMatch匹配规则函数：判断是否Stream流中的所有元素都不符合某一个"匹配规则"。
        boolean b1 = list.stream()
                .noneMatch(x -> x.getAge() < 70);
        System.out.println(b1);
    }

    /**
     * 元素查找与Optional
     */
    @Test
    public void test3(){
//        从列表中按照顺序查找第一个年龄大于40的员工。

        // 匿名函数查找
        StreamTestVo streamTestVo = list.stream()
                .filter(new Predicate<StreamTestVo>() {
                    @Override
                    public boolean test(StreamTestVo streamTestVo) {
                        return streamTestVo.getAge() > 40;
                    }
                }).findFirst().get();
        System.out.println(streamTestVo);
        // lamdba表达式查找
        Optional<StreamTestVo> optional = list.stream()
                .filter(x -> x.getAge() > 40)
                .findFirst();
        StreamTestVo streamTestVo2 = optional.get();
        System.out.println(streamTestVo2);
        /**
         * 总结：
         * Optional类代表一个值存在或者不存在。在java8中引入，这样就不用返回null了。避免空指针
         *
         * isPresent() 将在 Optional 包含值的时候返回 true , 否则返回 false 。
         * ifPresent(Consumer block) 会在值存在的时候执行给定的代码块。我们在第3章
         * 介绍了 Consumer 函数式接口；它让你传递一个接收 T 类型参数，并返回 void 的Lambda
         * 表达式。
         * T get() 会在值存在时返回值，否则?出一个 NoSuchElement 异常。
         * T orElse(T other) 会在值存在时返回值，否则返回一个默认值。
         */
        boolean present = list.stream()
                .filter(x -> x.getAge() > 40)
                .findFirst()
                .isPresent();
        System.out.println(present);

         list.stream()
                .filter(x -> x.getAge() > 40)
                .findFirst()
                .ifPresent(System.out::print);
        list.stream()
                .filter(x -> x.getAge() > 40)
                .findFirst()
                .orElse(new StreamTestVo(10,45,"M","xiaodei","xiaodei") );

    }







}
